package com.example.rfb.serviceloader;

import com.example.rfb.serviceloader.internal.IServiceProvider;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.ServiceConfigurationError;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;

public class AnnotationServiceLoader <S> implements ServiceLoader<S> {
    private final Class<S> service;
    private ClassLoader classLoader;
    private Collection<Class<? extends S>> classes;
    private AnnotationServiceLoader<S>.LazyIterator lookupIterator;

    private AnnotationServiceLoader(Class<S> svc) {
        this.service = (Class)requireNonNull(svc, "Service interface cannot be null");
        this.classLoader = this.getClass().getClassLoader();
    }

    private AnnotationServiceLoader(Class<S> svc, ClassLoader classLoader) {
        this.service = (Class)requireNonNull(svc, "Service interface cannot be null");
        this.classLoader = classLoader;
    }

    public void reload() {
        try {
            IServiceProvider<S> serviceProvider = this.getServiceProvider();
            this.classes = serviceProvider.provide();
            this.lookupIterator = new AnnotationServiceLoader.LazyIterator(this.service);
        } catch (Exception var2) {
            throw new ServiceConfigurationError(this.service.getName() + ": " + var2.getMessage());
        }
    }

    private static void fail(Class<?> service, String msg, Throwable cause) throws ServiceConfigurationError {
        throw new ServiceConfigurationError(service.getName() + ": " + msg, cause);
    }

    public Iterator<S> iterator() {
        this.init();
        return new Iterator<S>() {
            public boolean hasNext() {
                return AnnotationServiceLoader.this.lookupIterator.hasNext();
            }

            public S next() {
                return AnnotationServiceLoader.this.lookupIterator.next();
            }

            public void remove() {
                throw new UnsupportedOperationException();
            }
        };
    }

    private void init() {
        if (this.lookupIterator == null) {
            this.reload();
        }

    }

    public static <S> ServiceLoader<S> load(Class<S> service) {
        return new AnnotationServiceLoader(service);
    }

    public static <S> ServiceLoader<S> load(Class<S> service, ClassLoader classLoader) {
        return new AnnotationServiceLoader(service, classLoader);
    }

    private static <T> T requireNonNull(T obj, String message) {
        if (obj == null) {
            throw new NullPointerException(message);
        } else {
            return obj;
        }
    }

    private IServiceProvider<S> getServiceProvider() throws IllegalAccessException, InstantiationException {
        try {
            String packageName = this.service.getPackage().getName();
            Class<IServiceProvider<S>> serviceProviderClass = (Class<IServiceProvider<S>>)classLoader.loadClass(packageName + ".Provider_" + this.service.getSimpleName());
            return serviceProviderClass.newInstance();
        } catch (ClassNotFoundException var3) {
            Logger.getLogger("ServiceLoader").log(Level.ALL, "No Provider for" + this.service.getSimpleName() + ", Please Check whether annotationProcessor for app used");
            return new AnnotationServiceLoader.EmptyServiceProvider();
        }
    }

    private static class EmptyFuture<S> implements Future<Iterator<S>> {
        private EmptyFuture() {
        }

        public boolean cancel(boolean b) {
            return false;
        }

        public boolean isCancelled() {
            return false;
        }

        public boolean isDone() {
            return false;
        }

        public Iterator<S> get() {
            return (new ArrayList()).iterator();
        }

        public Iterator<S> get(long l, TimeUnit timeUnit) {
            return (new ArrayList()).iterator();
        }
    }

    private static class EmptyServiceProvider<S> implements IServiceProvider<S> {
        private EmptyServiceProvider() {
        }

        public Collection<Class<? extends S>> provide() {
            return new ArrayList();
        }
    }

    private class LazyIterator implements Iterator<S> {
        Class<S> service;
        Iterator<Class<? extends S>> iterator;

        private LazyIterator(Class<S> service) {
            this.service = service;
            this.iterator = AnnotationServiceLoader.this.classes.iterator();
        }

        private S nextService() throws RuntimeException {
            if (!this.iterator.hasNext()) {
                throw new NoSuchElementException();
            } else {
                Class<? extends S> c = (Class)this.iterator.next();
                if (!this.service.isAssignableFrom(c)) {
                    ClassCastException cce = new ClassCastException(this.service.getCanonicalName() + " is not assignable from " + c.getCanonicalName());
                    AnnotationServiceLoader.fail(this.service, "Provider " + c.getName() + " not a subtype", cce);
                }

                try {
                    return this.service.cast(c.newInstance());
                } catch (Exception var3) {
                    throw new ServiceConfigurationError(var3.getMessage());
                }
            }
        }

        public boolean hasNext() {
            return this.iterator.hasNext();
        }

        public S next() {
            return this.nextService();
        }
    }
}